/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * OptionsPanel.java
 *
 * Created on 23 Νοε 2008, 8:34:12 μμ
 */
package tools.options;

import com.googlecode.soptions.Option;
import java.awt.Component;
import java.awt.Font;
import javax.swing.SpinnerModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import tools.MySeriesLogger;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.logging.Level;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import myComponents.MyMessages;
import myComponents.MyUsefulFunctions;
import myComponents.myGUI.MyDraggable;
import myseriesproject.MySeries;
import com.googlecode.svalidators.formcomponents.ValidationGroup;
import help.HelpWindow;
import java.awt.BorderLayout;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.JSlider;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.xml.parsers.ParserConfigurationException;
import myComponents.myGUI.MyFont;
import myseriesproject.actions.ApplicationActions;
import org.xml.sax.SAXException;
import tools.languages.Language;
import tools.options.panels.Appearance;
import tools.options.panels.General;
import tools.options.panels.Internet;
import tools.options.panels.Performance;
import tools.options.panels.Renaming;
import tools.options.panels.Subtitles;

/**
 *
 * @author lordovol
 */
public class OptionsPanel extends MyDraggable {

  public static final String GENERAL = "General";
  public static final String INTERNET = "Internet";
  public static final String RENAMING = "Renaming";
  public static final String APPEARANCE = "Appearance";
  public static final String PERFORMANCE = "Performance";
  public static final String SUBTITLES = "Subtitles";
  public static final long serialVersionUID = 5676235253653L;
  private MySeries m;
  private DefaultComboBoxModel model_laf = new DefaultComboBoxModel();
  General general = new General();
  Appearance appearance = new Appearance();
  Internet internet = new Internet();
  Renaming renaming = new Renaming();
  Performance performance = new Performance();
  Subtitles subtitles = new Subtitles();
  public JPanel[] panels = {general, appearance, internet, renaming, performance, subtitles};
  private TreeModel optionsTreeModel;
  private JPanel currentPanel;

  /** Creates new form OptionsPanel
   * @param m MySeries main form
   */
  public OptionsPanel(MySeries m) {
    this.m = m;
    MySeriesLogger.logger.log(Level.INFO, "Initializing components");
    createTreeModel();
    initComponents();
    tree.setSelectionRow(1);
    MySeriesLogger.logger.log(Level.FINE, "Components initialized");
    setLocationRelativeTo(m);
    setVisible(true);
  }

  /** This method is called from within the constructor to
   * initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is
   * always regenerated by the Form Editor.
   */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        panel_DateFormatHelp = new javax.swing.JPanel();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jMenu2 = new javax.swing.JMenu();
        jPanel1 = new javax.swing.JPanel();
        lb_title = new javax.swing.JLabel();
        bt_cancel = new myComponents.myGUI.buttons.MyButtonCancel();
        bt_help = new myComponents.myGUI.buttons.MyButtonHelp();
        bt_ok = new myComponents.myGUI.buttons.MyButtonOk();
        splitpane = new javax.swing.JSplitPane();
        left = new javax.swing.JScrollPane();
        tree = new javax.swing.JTree();
        right = new javax.swing.JPanel();
        margin = new javax.swing.JLabel();

        javax.swing.GroupLayout panel_DateFormatHelpLayout = new javax.swing.GroupLayout(panel_DateFormatHelp);
        panel_DateFormatHelp.setLayout(panel_DateFormatHelpLayout);
        panel_DateFormatHelpLayout.setHorizontalGroup(
            panel_DateFormatHelpLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 100, Short.MAX_VALUE)
        );
        panel_DateFormatHelpLayout.setVerticalGroup(
            panel_DateFormatHelpLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 100, Short.MAX_VALUE)
        );

        jMenu1.setText("File");
        jMenuBar1.add(jMenu1);

        jMenu2.setText("Edit");
        jMenuBar1.add(jMenu2);

        setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
        setUndecorated(true);

        jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        jPanel1.setMaximumSize(new java.awt.Dimension(800, 500));
        jPanel1.setMinimumSize(new java.awt.Dimension(627, 430));

        lb_title.setFont(lb_title.getFont().deriveFont(lb_title.getFont().getStyle() | java.awt.Font.BOLD, lb_title.getFont().getSize()+2));
        lb_title.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        lb_title.setText("Options");

        bt_cancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bt_cancelActionPerformed(evt);
            }
        });

        bt_help.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bt_helpActionPerformed(evt);
            }
        });

        bt_ok.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bt_okActionPerformed(evt);
            }
        });

        splitpane.setDividerLocation(150);

        left.setMinimumSize(new java.awt.Dimension(74, 332));

        tree.setModel(optionsTreeModel);
        tree.setMaximumSize(new java.awt.Dimension(200, 400));
        tree.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
            public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
                treeValueChanged(evt);
            }
        });
        left.setViewportView(tree);

        splitpane.setLeftComponent(left);

        right.setPreferredSize(new java.awt.Dimension(200, 74));
        right.setLayout(new java.awt.BorderLayout());

        margin.setMaximumSize(new java.awt.Dimension(20, 14));
        margin.setMinimumSize(new java.awt.Dimension(20, 14));
        margin.setPreferredSize(new java.awt.Dimension(20, 14));
        right.add(margin, java.awt.BorderLayout.LINE_START);

        splitpane.setRightComponent(right);

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                        .addGap(58, 58, 58)
                        .addComponent(lb_title, javax.swing.GroupLayout.PREFERRED_SIZE, 466, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 54, Short.MAX_VALUE)
                        .addComponent(bt_help, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(bt_cancel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(bt_ok, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(splitpane, javax.swing.GroupLayout.DEFAULT_SIZE, 638, Short.MAX_VALUE)
                        .addContainerGap())))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
                    .addComponent(lb_title)
                    .addComponent(bt_cancel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(bt_help, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(splitpane, javax.swing.GroupLayout.DEFAULT_SIZE, 381, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(bt_ok, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

  /**
   * Saves the options
   * @throws java.io.IOException
   */
  private void saveOptions() throws IOException, ParseException {
    try {
      // Check for illegal arguments in date format
      MySeriesLogger.logger.log(Level.INFO, "Saving options");
      SimpleDateFormat f = new SimpleDateFormat(String.valueOf(general.combobox_dateFormat.getSelectedItem()));
      getOptionsComponents();
      MySeries.options.save();
      MySeries.options.readOptions();
      dispose();
      MySeries.glassPane.deactivate();
    } catch (FileNotFoundException ex) {
      MySeriesLogger.logger.log(Level.SEVERE, "Could not save the options", ex);
    } catch (ParserConfigurationException ex) {
      MySeriesLogger.logger.log(Level.SEVERE, "Could not save the options", ex);
    } catch (SAXException ex) {
      MySeriesLogger.logger.log(Level.SEVERE, "Could not save the options", ex);
    } catch (IOException ex) {
      MySeriesLogger.logger.log(Level.SEVERE, "Could not write to options file", ex);
    } catch (IllegalArgumentException ex) {
      MyMessages.error("Wrong Arguments", "The date format pattern you provided is invalid", true);
      MySeriesLogger.logger.log(Level.WARNING, "The date format "
          + String.valueOf(general.combobox_dateFormat.getSelectedItem())
          + " pattern you provided is invalid", ex);
    }
  }

  private void bt_cancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bt_cancelActionPerformed
    MySeriesLogger.logger.log(Level.INFO, "Canceled by the user");
    dispose();
    MySeries.glassPane.deactivate();
  }//GEN-LAST:event_bt_cancelActionPerformed

  private void bt_helpActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bt_helpActionPerformed
    if (currentPanel.equals(general)) {
      MySeriesLogger.logger.log(Level.INFO, "Showing General options help window");
      HelpWindow helpWindow = new HelpWindow(HelpWindow.GENERAL_OPTIONS);
    } else if (currentPanel.equals(internet)) {
      MySeriesLogger.logger.log(Level.INFO, "Showing Internet options help window");
      HelpWindow helpWindow = new HelpWindow(HelpWindow.INTERNET_OPTIONS);
    } else if (currentPanel.equals(renaming)) {
      MySeriesLogger.logger.log(Level.INFO, "Showing Rename options help window");
      HelpWindow helpWindow = new HelpWindow(HelpWindow.RENAME_OPTIONS);
    } else if (currentPanel.equals(appearance)) {
      MySeriesLogger.logger.log(Level.INFO, "Showing appearance options help window");
      HelpWindow helpWindow = new HelpWindow(HelpWindow.APPEARANCE_OPTIONS);
    } else if (currentPanel.equals(performance)) {
      MySeriesLogger.logger.log(Level.INFO, "Showing performance options help window");
      HelpWindow helpWindow = new HelpWindow(HelpWindow.PERFORMANCE_OPTIONS);
    } else if (currentPanel.equals(subtitles)) {
      MySeriesLogger.logger.log(Level.INFO, "Showing subtitles options help window");
      HelpWindow helpWindow = new HelpWindow(HelpWindow.SUBTITLES_OPTIONS);
    }
  }//GEN-LAST:event_bt_helpActionPerformed

  private void bt_okActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bt_okActionPerformed
    boolean skinChange = false;
    ValidationGroup group = new ValidationGroup();
    group.addComponent(internet.textfield_port);
    group.addComponent(internet.textfield_proxy);
    group.addComponent(subtitles.combo_secondaryLang);
    group.addComponent(renaming.tf_episodeSep);
    group.addComponent(renaming.tf_titleSep);
    group.addComponent(renaming.tf_seasonSep);
    group.addComponent(general.tf_videoApp);
    MySeriesLogger.logger.log(Level.INFO, "Validating user input");
    if (!group.validate()) {
      MySeriesLogger.logger.log(Level.WARNING, "Validation failed\nError message: {0}", group.getErrorMessage());
      MyMessages.validationError("Options Form", group.getErrorMessage());
      return;
    }
    try {
      String mess = "";
      saveOptions();
      MySeriesLogger.logger.setLevel(Level.parse(MySeries.options.getStringOption(MySeriesOptions.DEBUG_MODE)));
      MyUsefulFunctions.createMemoryCons(m);
      MyUsefulFunctions.feedUpdater(m);
      MySeries.languages.setPrimary((Language) subtitles.combo_primaryLang.getSelectedItem());
      MySeries.languages.setSecondary((Language) subtitles.combo_secondaryLang.getSelectedItem());
      MyUsefulFunctions.initInternetConnection();
      MySeriesLogger.logger.setLevel(Level.parse(MySeries.options.getStringOption(MySeriesOptions.DEBUG_MODE)));
      m.createComboBox_filters();
      if (!appearance.oldFontFace.equals(MySeries.options.getStringOption(MySeriesOptions.FONT_FACE))) {
        MySeriesLogger.logger.log(Level.INFO, "Font face changed");
        mess = "Font face, ";
      }
      if (!appearance.oldFontSize.equals(MySeries.options.getStringOption(MySeriesOptions.FONT_SIZE))) {
        MySeriesLogger.logger.log(Level.INFO, "Font size changed");
        mess += "Font size, ";
      }
      if (!appearance.oldColor.equals(MySeries.options.getColorOption(MySeriesOptions.SKIN_COLOR))) {
        MySeriesLogger.logger.log(Level.INFO, "Skin color changed");
        mess += "Skin color, ";
        skinChange = true;
      }
      if ((!appearance.oldUseSkin && appearance.checkbox_dontUseSkin.isSelected()) || (appearance.oldUseSkin && !appearance.checkbox_dontUseSkin.isSelected())) {
        MySeriesLogger.logger.log(Level.INFO, "Skin usage changed");
        mess += "Skin, ";
        skinChange = true;
      }
      if (!appearance.oldLaf.equals(MySeries.options.getStringOption(MySeriesOptions.LOOK_AND_FEEL))) {
        MySeriesLogger.logger.log(Level.INFO, "Look and feel changed");
        mess += "Look and Feel, ";
      }
      mess = mess.trim();

      if (!mess.equals("")) {
        if (!skinChange) {
          MyFont.SetMyFont();
          try {
            appearance.lap.setLookAndFeel(MySeries.options.getStringOption(MySeriesOptions.LOOK_AND_FEEL));
          } catch (Exception ex) {
            Logger.getLogger(OptionsPanel.class.getName()).log(Level.SEVERE, null, ex);
          }
          SwingUtilities.updateComponentTreeUI(m);
          SwingUtilities.updateComponentTreeUI(m.seriesPopUp);
          SwingUtilities.updateComponentTreeUI(m.episodesPopUp);
          // m.pack();
          m.setExtendedState(MySeries.options.getIntegerOption(MySeriesOptions.WINDOW_STATE));
        } else {
          mess = "Skin changes ";
          int a = MyMessages.confirm("Options", mess + "will take effect when you restart the application\nRestart now?", false);
          if (a == JOptionPane.YES_OPTION) {
            ApplicationActions.restartApplication(m);
          }
        }
      }
    } catch (IOException ex) {
      MySeriesLogger.logger.log(Level.SEVERE, "Could not write to options file", ex);
    } catch (ParseException ex) {
      MySeriesLogger.logger.log(Level.SEVERE, "Could not parse options objects", ex);
    }
  }//GEN-LAST:event_bt_okActionPerformed

  private void treeValueChanged(javax.swing.event.TreeSelectionEvent evt) {//GEN-FIRST:event_treeValueChanged
    TreePath path = evt.getNewLeadSelectionPath();
    DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
    String selection = (String) node.getUserObject();
    BorderLayout layout = (BorderLayout) right.getLayout();
    Component c = layout.getLayoutComponent(right, BorderLayout.CENTER);
    if (c != null) {
      right.remove(c);
      right.validate();
      right.repaint();
    }
    if (selection.equals(GENERAL)) {
      right.add(general, BorderLayout.CENTER);
      currentPanel = general;
    } else if (selection.equals(APPEARANCE)) {
      right.add(appearance, BorderLayout.CENTER);
      currentPanel = appearance;
    } else if (selection.equals(INTERNET)) {
      right.add(internet, BorderLayout.CENTER);
      currentPanel = internet;
    } else if (selection.equals(RENAMING)) {
      right.add(renaming, BorderLayout.CENTER);
      currentPanel = renaming;
    } else if (selection.equals(PERFORMANCE)) {
      right.add(performance, BorderLayout.CENTER);
      currentPanel = performance;
    } else if (selection.equals(SUBTITLES)) {
      right.add(subtitles, BorderLayout.CENTER);
      currentPanel = subtitles;
    } else {
      tree.expandRow(1);
      tree.setSelectionRow(1);
      currentPanel = general;
    }
    right.validate();
    right.repaint();
  }//GEN-LAST:event_treeValueChanged

  private Font getSelectedFont() {
    Font font = new Font((String) appearance.combobox_fonts.getSelectedItem(), Font.PLAIN, (int) Float.parseFloat(String.valueOf(appearance.spinner_fontSize.getValue())));
    return font;
  }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private myComponents.myGUI.buttons.MyButtonCancel bt_cancel;
    private myComponents.myGUI.buttons.MyButtonHelp bt_help;
    private myComponents.myGUI.buttons.MyButtonOk bt_ok;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JLabel lb_title;
    private javax.swing.JScrollPane left;
    private javax.swing.JLabel margin;
    private javax.swing.JPanel panel_DateFormatHelp;
    private javax.swing.JPanel right;
    private javax.swing.JSplitPane splitpane;
    private javax.swing.JTree tree;
    // End of variables declaration//GEN-END:variables

  /**
   * Parsing all the options panels for option components
   */
  private void getOptionsComponents() {
    for (int i = 0; i < panels.length; i++) {
      parse(panels[i]);
    }
  }

  /**
   * Parsing a jpanel and gets components with a name diff than "noname"<br />
   * Then sets the option with the name of the component to the value of the componont
   * @param panel
   */
  private void parse(JPanel panel) {
    MySeriesLogger.logger.log(Level.INFO, "Parsing panel {0}", panel.getName());
    Component[] c = panel.getComponents();
    Option option;
    for (int i = 0; i < c.length; i++) {
      if (c[i].getName() == null) {
      } else if (!c[i].getName().equals("noname") && !c[i].getName().equals("null")) {
        String name = c[i].getName();
        option = MySeries.options.getOption(name);
        option.setValue(getValue(c[i]));
        MySeries.options.setOption(option);
      }
    }
  }

  /**
   * Getting the value and type of a component <br />
   * Components are JSpinner, JCheckBox, JComboBox, JTextField, JButton, JSlider
   * @param c The component
   * @return the value of the component
   */
  private Object getValue(Component c) {
    MySeriesLogger.logger.log(Level.INFO, "Getting {0} components value and type", c.getName());
    Object val = "";
    Object type = Option.STRING_CLASS;
    if (c instanceof JSpinner) {
      JSpinner spin = (JSpinner) c;
      val = spin.getValue();
      SpinnerModel model = spin.getModel();
      
    } else if (c instanceof JCheckBox) {
      JCheckBox check = (JCheckBox) c;
      val = check.isSelected();
    } else if (c instanceof JTextField) {
      JTextField text = (JTextField) c;
      val = text.getText();
    } else if (c instanceof JComboBox) {
      JComboBox combo = (JComboBox) c;
      // In some combos get the item instead of index
      String name = combo.getName();
      if (MyUsefulFunctions.isInArray(MySeriesOptions._COMBO_OPTIONS_, name)) {
        val = String.valueOf(combo.getSelectedItem());
      } else {
        val = combo.getSelectedIndex();
      }
    } else // Get color buttons
    if (c instanceof JButton) {
      JButton button = (JButton) c;
      val =  button.getBackground();
    } else if (c instanceof JSlider) {
      JSlider sl = (JSlider) c;
      val = sl.getValue();
    }
    MySeriesLogger.logger.log(Level.INFO, "Components value is {0}", val);
    return val;
  }

  private void createTreeModel() {
    MySeriesLogger.logger.log(Level.INFO, "Creating the tree model");
    DefaultMutableTreeNode top =
        new DefaultMutableTreeNode("Options");
    for (int i = 0; i < panels.length; i++) {
      String name = panels[i].getName();
      top.add(new DefaultMutableTreeNode(name));
    }
    optionsTreeModel = new DefaultTreeModel(top);
  }
}
